#!/usr/bin/python

STARK = 'Stark'
TYRELL = 'Tyrell'
GREYJOY = 'Greyjoy'
LANNISTER = 'Lannister'
BARATHEON = 'Baratheon'
MARTELL = 'Martell'

HOUSES = [STARK, TYRELL, GREYJOY, LANNISTER, BARATHEON, MARTELL]

MAX_POWER = 20
MIN_POWER = 0
STARTING_POWER = 5

MAX_SUPPLY = 6
MIN_SUPPLY = 0

# TODO(codexile): set max values for these.
MAX_FOOTMEN = None
MAX_KNIGHTS = None
MAX_SHIPS = None


class WesterosCard(object):
  """Cards for the Westeros phase."""


class HouseCard(object):
  """One of the various house combat cards in the game."""
  def __init__(self, name, strength, swords=0, fortifications=0, text=None):
    self.name = name
    self.strength = strength
    self.swords = swords
    self.fortifications = fortifications
    if text:
      self.text = text
    else:
      self.text = ''


class Player(object):

  def __init__(self, house):
    self.house = house
    self.power = STARTING_POWER
    self.supply = MIN_POWER

  def AddPower(self, amount):
    new_power = self.power + amount
    if new_power > MAX_POWER:
      self.power = MAX_POWER
    else:
      self.power = new_power

  def SubtractPower(self, amount):
    new_power = self.power - amount
    if new_power < MIN_POWER:
      self.power = MIN_POWER
    else:
      self.power = new_power

  def AddSupply(self, amount):
    new_supply = self.supply + amount
    if new_supply > MAX_SUPPLY:
      self.supply = MAX_SUPPLY
    else:
      self.supply = new_supply

  def ResetSupply(self):
    self.supply = MIN_SUPPLY


class Region(object):
  def __init__(self, name, muster=0, crowns=0, barrels=0, water=False,
               capital=None):
    self.name = name
    self.muster = muster
    self.crowns = crowns
    self.barrels = barrels
    self.water = water
    self.capital = capital

    self._owner = None

  @property
  def owner(self):
    if self.capital and not self._owner:
      return self.capital
    return self._owner


class Board(object):
  def __init__(self):
    # TODO(codexile): don't just add all the houses as players.
    self.players = {}
    for house in HOUSES:
      self.players[house] = Player(house)

    # convert an interable of Region objects to a dict of {name: region}
    self.regions = dict(map(lambda x: (x.name, x), GetRegions()))

    self.adjacency = {}
    for region in self.regions:
      self.adjacency[region] = []

    self.RecalculateSupply()

  def AdjacentTo(self, region, touches):
    if type(touches) != list:
      touches = [touches]

    self.adjacency[region].extend(touches)

    for touching in touches:
      self.adjacency[touching] = region

  def RecalculateSupply(self):
    for player in self.players.itervalues():
      player.ResetSupply()

    for region in self.regions.itervalues():
      if region.owner and region.barrels:
        self.players[region.owner].AddSupply(region.barrels)

  def AwardPower(self):
    for region in self.regions.itervalues():
      if region.owner and region.crowns:
        self.players[region.owner].AddPower(region.crowns)


def GetRegions():
  regions = []

  # water regions
  regions.append(Region('Bay of Ice', water=True))
  regions.append(Region('The Shivering Sea', water=True))
  regions.append(Region('The Narrow Sea', water=True))
  regions.append(Region('Sunset Sea', water=True))
  regions.append(Region('The Golden Sound', water=True))
  regions.append(Region('Ironman\'s Bay', water=True))
  regions.append(Region('Shipbreaker Bay', water=True))
  regions.append(Region('Blackwater Bay', water=True))
  regions.append(Region('West Summer Sea', water=True))
  regions.append(Region('East Summer Sea', water=True))
  regions.append(Region('Sea of Dorne', water=True))
  regions.append(Region('Redwyne Straights', water=True))

  # capitals
  regions.append(Region('Highgarden', muster=2, barrels=2, capital=TYRELL))
  regions.append(Region('Lannisport', muster=2, barrels=2, capital=LANNISTER))
  regions.append(Region('Pyke', muster=2, barrels=1, crowns=1, capital=GREYJOY))
  regions.append(Region('Winterfell', muster=2, barrels=1, crowns=1,
                        capital=STARK))
  regions.append(Region('Sunspear', muster=2, barrels=1, crowns=1,
                        capital=MARTELL))
  regions.append(Region('Dragonstone', muster=2, barrels=1, crowns=1,
                        capital=BARATHEON))

  # other
  regions.append(Region('The Stony Shore', barrels=1))
  regions.append(Region('Castle Black', crowns=1))
  regions.append(Region('Karhold', crowns=1))
  regions.append(Region('White Harbor', muster=1))
  regions.append(Region('Widow\'s Watch', barrels=1))
  regions.append(Region('Moat Cailin', muster=1))
  regions.append(Region('Greywater Watch', barrels=1))
  regions.append(Region('Flint\'s Finger', muster=1))
  regions.append(Region('Seagard', muster=2, barrels=1, crowns=1))
  regions.append(Region('The Twins', crowns=1))
  regions.append(Region('The Fingers', barrels=1))
  regions.append(Region('The Mountains of the Moon', barrels=1))
  regions.append(Region('The Eyrie', muster=1, barrels=1))
  regions.append(Region('Riverrun', muster=2, barrels=1, crowns=1))
  regions.append(Region('Crackclaw Point', muster=1))
  regions.append(Region('Harrenhal', muster=1, crowns=1))
  regions.append(Region('Stoney Stept', crowns=1))
  regions.append(Region('Searoad Marches', barrels=1))
  regions.append(Region('Blackwater', barrels=2))
  regions.append(Region('The Reach', muster=1))
  regions.append(Region('Kings Landing', muster=2, crowns=2))
  regions.append(Region('Kingswood', crowns=1, barrels=1))
  regions.append(Region('Storms End', muster=1))
  regions.append(Region('The Boneway', crowns=1))
  regions.append(Region('Prince\'s Pass', crowns=1, barrels=1))
  regions.append(Region('Starfall', muster=1, barrels=1))
  regions.append(Region('Salt Shore', barrels=1))
  regions.append(Region('Yronwood', muster=1))
  regions.append(Region('Three Towers', barrels=1))
  regions.append(Region('Dornish Marshes', crowns=1))
  regions.append(Region('Oldtown', muster=2))
  regions.append(Region('The Arbor', crowns=1))

  return regions


if __name__ == '__main__':
  board = Board()
  for house, player in board.players.iteritems():
    print 'starting supply: ', house, player.supply
  regions = GetRegions()
  for region in regions:
    assert len([r for r in regions if r.name == region.name]) == 1

  for region in regions:
    msg = region.name
    if region.capital:
      msg += ', the %s capital' % region.capital
    if region.muster == 1:
      msg += ', stronghold'
    if region.muster == 2:
      msg += ', fortress'
    if region.barrels:
      msg += ', %s barrels' % region.barrels
    if region.crowns:
      msg += ', %s crowns' % region.crowns
    if region.water:
      msg += ', a water territory'
    msg += '.'
    print msg

  for house, player in board.players.iteritems():
    print 'starting power: ', house, player.power

  board.AwardPower()
  for house, player in board.players.iteritems():
    print 'power after: ', house, player.power
